/*
 * bw_Sys.cpp
 *
 *  Created on: 2018年11月9日
 *      Author: linsainan
 */

#include "bw_Sys.h"
#include "bw_FcgiRequest.h"
#include "bw_dbcol.h"
#include "bw_DateTime.h"
#include "bw_Sqlite.h"
#include "cJSON.h"
#include "bw_jskey.h"
#include "bw_public.h"
#include "public.h"

#include "bw_net_cfg.h"

using namespace bwcgi;

extern char g_outbuf[];

cJSON *retMesgHead(cJSON *root,unsigned int retcode,const char *retmsg)
{
	if((NULL == root) || !retmsg)
	{
		cgi_debug("root NULL");
	}
	
	cJSON *p_obj = NULL;
	
	cJSON_AddNumberToObject(root,"retCode",retcode);
	cJSON_AddStringToObject(root,"retMsg",retmsg);

	p_obj = cJSON_CreateObject();
	cJSON_AddItemToObject(root,"retData",p_obj);

	return p_obj;
}

int check_ip_mask_gateway(unsigned int ip, unsigned int mask, unsigned int gateway)//网络序
{
	unsigned int temp_get_mask = 0;
	
	temp_get_mask = Addr_swap(mask);//大端序
	while(temp_get_mask & 0x80000000)//掩码合法性
	{
		temp_get_mask = temp_get_mask << 1;
	}
	if(temp_get_mask > 0) 
	{
		return 1;//掩码不合法
	}

	if((mask&ip)!=(mask&gateway))//同一网段检测
	{
		return 2;
	}

	return 0;
}

// 系统日志获取
const char* log_list(const char* json) {
	eENC_ERROR code = BWENC_ERROR_UNKNOW;
	cJSON* root = cJSON_Parse(json);
	if (!root) {
		cgi_debug("error");
		code = BWENC_ERROR_INVALID_PARAM;
		return bwenc_common_ack(code);
	}

	cJSON* param = cJSON_GetObjectItem(root, KEY_PARAM);
	if (!param) {
		cgi_debug("error");
		code = BWENC_ERROR_INVALID_PARAM;
		cJSON_Delete(root);
		return bwenc_common_ack(code);
	}
	int page = 1;
	cJSON *p_tmp = cJSON_GetObjectItem(param, "page");
	if (p_tmp && p_tmp->valueint > 0) {
		page = p_tmp->valueint;
	}

	int page_size = 30;
	p_tmp = cJSON_GetObjectItem(param, "page_size");
	if (p_tmp && p_tmp->valueint > 0) {
		page_size = p_tmp->valueint;
	}

	BWSqlite db(BWENC_DATABASE);
	char sql[SZ_1K] = { 0 };
	snprintf(sql, sizeof(sql), "SELECT count(id) as total FROM %s", DBTBL_LOG);

	int total = 0;
	BWRow row = db.QueryRow(sql);
	if (!row.empty()) {
		std::string t_str = row["total"];
		total = atoi(t_str.c_str());
	}

	snprintf(sql, sizeof(sql),
			"SELECT %s,%s,%s,%s FROM %s order by id desc limit %d offset %d",
			DBCOL_ID,
			DBCOL_TYPE, DBCOL_DETAIL, DBCOL_TIME, DBTBL_LOG, page_size,
			page_size * (page - 1));
	BWRows rows = db.QeuryRows(sql);

	// 构造返回json
	cJSON *pout_root = NULL;
	cJSON *p_obj = NULL;
	cJSON *p_arr = NULL;
	cJSON *arr_tmp = NULL;

	pout_root = cJSON_CreateObject();
	cJSON_AddNumberToObject(pout_root, "retCode", 0);
	cJSON_AddStringToObject(pout_root, "retMsg", "SUCCESS");
	p_obj = cJSON_CreateObject();
	cJSON_AddItemToObject(pout_root, "retData", p_obj);
	cJSON_AddNumberToObject(p_obj, "total", total);
	p_arr = cJSON_CreateArray();
	cJSON_AddItemToObject(p_obj, "log_list", p_arr);

	if (!rows.empty()) {
		for (std::vector<BWRow>::size_type i = 0; i < rows.size(); i++) {
			BWRow temRow = rows[i];
			arr_tmp = cJSON_CreateObject();
			cJSON_AddItemToArray(p_arr, arr_tmp);

			cJSON_AddStringToObject(arr_tmp, "id", temRow[DBCOL_ID].c_str());
			cJSON_AddStringToObject(arr_tmp, "type",
					temRow[DBCOL_TYPE].c_str());
			cJSON_AddStringToObject(arr_tmp, "detail",
					temRow[DBCOL_DETAIL].c_str());
			cJSON_AddStringToObject(arr_tmp, "time",
					temRow[DBCOL_TIME].c_str());
		}
	}

	char* str = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf, 0, get_g_oubuf_size());
	memcpy(g_outbuf, str, strlen(str));
	free(str);

	cJSON_Delete(pout_root);
	cJSON_Delete(root);
	return g_outbuf;
}

// TODO 系统设置-获取设置信息
int syscfg_getNet(ETH_Item *data)
{
	int eth_id = 0;
	if(NULL == data)
	{
		return 1;
	}

	for(eth_id = 0; eth_id < 3; eth_id++)
	{
		stNetParam nps;
		//eth_id = eth_id > ETH_MAX ? ETH_MAX -1 : eth_id;
		bw_net_getparams((char*)g_encset_mst->enc_ethdevname[eth_id], &nps);

		data->mask = inet_addr(nps.netmask);
		data->gateway = inet_addr(nps.gateway);
		data->ip = Addr_swap(g_encset_mst->enc_ethdevipaddr[eth_id][0]);
		snprintf((char *)data->mac_str,sizeof(data->mac_str),"%s",nps.mac_str);
	}
	
	return 0;	
}

const char *sysinfo_response()
{
	cJSON *pout_root = NULL;
	cJSON *p_data = NULL;
	char *p_backet=NULL;
	char tmpbuf[100] = {0};

	ETH_Item netdata[3];
	memset(&netdata,0,sizeof(netdata));
	syscfg_getNet(netdata);
	
	//构建返回网页的json；
	pout_root = cJSON_CreateObject();
	p_data = retMesgHead(pout_root,0,"SUCCESS");

	cJSON *p_input = cJSON_CreateObject();
	cJSON_AddItemToObject(p_data,"input_interface",p_input);
	cJSON_AddStringToObject( p_input, "ip", iptostr(netdata[0].ip));
	cJSON_AddStringToObject( p_input, "mask", iptostr(netdata[0].mask));
	cJSON_AddStringToObject( p_input, "gateway", iptostr(netdata[0].gateway));
	cJSON_AddStringToObject( p_input, "mac", (char *)netdata[0].mac_str);
	
	cJSON *p_output = cJSON_CreateObject();
	cJSON_AddItemToObject(p_data,"output_interface",p_output);
	cJSON_AddStringToObject( p_output, "ip", iptostr(netdata[1].ip));
	cJSON_AddStringToObject( p_output, "mask", iptostr(netdata[1].mask));
	cJSON_AddStringToObject( p_output, "gateway", iptostr(netdata[1].gateway));
	cJSON_AddStringToObject( p_output, "mac", (char *)netdata[1].mac_str);

	cJSON *p_manager = cJSON_CreateObject();
	cJSON_AddItemToObject(p_data,"manager_interface",p_manager);
	cJSON_AddStringToObject( p_manager, "ip", iptostr(netdata[2].ip));
	cJSON_AddStringToObject( p_manager, "mask", iptostr(netdata[2].mask));
	cJSON_AddStringToObject( p_manager, "gateway", iptostr(netdata[2].gateway));
	cJSON_AddStringToObject( p_manager, "mac", (char *)netdata[2].mac_str);

	cJSON_AddStringToObject(p_data,"cfg_version","1.0.0");
	cJSON_AddStringToObject(p_data,"sys_version","1.0.0");	
	cJSON_AddStringToObject(p_data,"ntp","www.ntp.com");
	sprintf(tmpbuf,"%d",1);
	cJSON_AddStringToObject(p_data,"time_type",tmpbuf);

	DateTime datetime;
	char timeStr[sizeof("yyyy-mm-dd hh:mm:ss")] = { '\0' };
	datetime.time2string(time(nullptr), timeStr);
	cJSON_AddStringToObject(p_data,"sys_time",timeStr);

	p_backet = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf,0,get_g_oubuf_size());
	strncpy(g_outbuf, p_backet, strlen(p_backet));

	free(p_backet);
	cJSON_Delete(pout_root);
	
	return g_outbuf;
}

const char* sys_info() 
{
	/*eENC_ERROR code = BWENC_ERROR_UNKNOW;
	cJSON *p_root = NULL;
	cJSON *p_para = NULL;
	//cJSON *p_tmp = NULL;
		
	p_root = cJSON_Parse(json);
	if (p_root == NULL)
	{
		cgi_debug("parse root error");
		goto error;
	}

	p_para = cJSON_GetObjectItem(p_root, KEY_PARAM);
	if (p_para == NULL)
	{
		cgi_debug("parse para error");
		goto error;
	}

	cJSON_Delete(p_root);*/
	return sysinfo_response();
	
/*error:
	cJSON_Delete(p_root);
	return bwenc_common_ack(code);*/
}

char * network_para_err(unsigned int retcode,const char *retmsg,unsigned char ethid)
{
	cJSON *pout_root = NULL;
	cJSON *p_data = NULL;
	char *p_backet=NULL;
	char tmpbuf[50]={0};
	
	//构建返回网页的json；
	pout_root = cJSON_CreateObject();
	p_data = retMesgHead(pout_root,retcode,retmsg);
	
	sprintf(tmpbuf,"%d",ethid);
	cJSON_AddStringToObject( p_data ,"eth_id", tmpbuf);

	p_backet = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf,0,get_g_oubuf_size());
	strncpy(g_outbuf, p_backet, strlen(p_backet));

	free(p_backet);
	cJSON_Delete(pout_root);
	
	return g_outbuf;
}

// TODO 系统设置-设置网口信息
int syscfg_set_todev(ETH_Item data)
{
	char mask_buf[64];
	char gw_buf[64];
	char ip_buf[64];
		
	sprintf(mask_buf,iptostr(data.mask));
	sprintf(gw_buf,iptostr(data.gateway));
	sprintf(ip_buf,iptostr(data.ip));
	cgi_debug("set %s: ip[%s], mask[%s], gw[%s]", (const char*)g_encset_mst->enc_ethdevname[data.eth_id], ip_buf, mask_buf, gw_buf);
	
#ifdef APP_FUNC
	bw_net_set_cfg((const char*)g_encset_mst->enc_ethdevname[data.eth_id], ip_buf, mask_buf, gw_buf);
#endif

	//配置mac
#ifdef APP_FUNC
	bw_net_set_mac((char *)g_encset_mst->enc_ethdevname[data.eth_id], (char *)data.mac_str);
#endif
	
	stNetParam nps;
	bw_net_getparams((char *)g_encset_mst->enc_ethdevname[data.eth_id], &nps);

	//写共享内存
	sem_wait(g_shrmsem);
	g_encset_mst->enc_ethdevipaddr[data.eth_id][0] = htonl(inet_addr(nps.ipaddr));

	g_encset_mst->enc_setvsion++;
	sem_post(g_shrmsem);

	return 0;
}

const char* nt_set(const char* json) 
{
	cJSON *p_root = NULL;
	cJSON *p_para = NULL;
	//cJSON *p_obj = NULL;
	cJSON *p_tmp = NULL;
	//cJSON *p_array = NULL;
	unsigned int get_mask = 0;
	unsigned int get_ip = 0;
	unsigned int get_gw = 0;
	//unsigned int temp_get_mask = 0;
	unsigned int code = 0;
	const char *retmsg="SUCCESS"; 
	//unsigned int i = 0;//j = 0;
	//unsigned int ret;

	ETH_Item data;

	p_root = cJSON_Parse(json);
	if (p_root == NULL)
	{
		cgi_debug("parse root error");
		goto error;
	}

	p_para = cJSON_GetObjectItem(p_root, "param");
	if (p_para == NULL)
	{
		cgi_debug("parse para error");
		goto error;
	}

	memset(&data,0,sizeof(data));

	p_tmp = cJSON_GetObjectItem(p_para, "type");
	if(NULL != p_tmp)
	{
		data.eth_id = p_tmp->valueint;
	}

	p_tmp = cJSON_GetObjectItem(p_para, "ip");
	if(NULL != p_tmp)
	{
		get_ip = ipstrtoint(p_tmp->valuestring);
	}

	p_tmp = cJSON_GetObjectItem(p_para, "mask");
	if(NULL != p_tmp)
	{
		get_mask = ipstrtoint(p_tmp->valuestring);
	}

	p_tmp = cJSON_GetObjectItem(p_para, "gateway");
	if(NULL != p_tmp)
	{
		get_gw = ipstrtoint(p_tmp->valuestring);
	}

	code = check_ip_mask_gateway(get_ip,get_mask,get_gw);
	if(code != 0)
	{
		//code = ret;
		retmsg = "error";
	}

	/*for(i=0; i < 3; i++)//ip不能相同
	{
		if(data.eth_id != i)
		{		
			if(Addr_swap(data.ip) == g_ipbakset->ethdevipaddr[i][0])
			{
				cgi_debug("ip same");
				code = ERROR_IP_SAME;
				retmsg = "ip can not same";
				goto error;
			}
		}
	}*/

	data.ip = get_ip;
	data.mask = get_mask;
	data.gateway = get_gw;
	
	p_tmp = cJSON_GetObjectItem(p_para, "mac");
	if(NULL != p_tmp)
	{
		snprintf((char *)data.mac_str,sizeof(data.mac_str),"%s",p_tmp->valuestring);
	}

	cgi_debug("eth_id:%d,ip:%x,mask:%x,gate:%x,mac:%s",data.eth_id,data.ip,data.mask,data.gateway,data.mac_str);
	
	code = syscfg_set_todev(data);
	
error:
	cJSON_Delete(p_root);
	return	network_para_err(code,retmsg,data.eth_id);
}

// TODO 升级开始以及升级成功/失败查询接口
const char* upgrade_status_response(unsigned int update_op) 
{
	/*cJSON *pout_root = NULL;
	cJSON *p_data = NULL;
	char *p_backet=NULL;
	char tmpbuf[50]={0};
	
	//构建返回网页的json；
	//pout_root = cJSON_CreateObject();
	//p_data = retMesgHead(pout_root,0,"SUCCESS");

	p_backet = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf,0,get_g_oubuf_size());
	strncpy(g_outbuf, p_backet, strlen(p_backet));

	free(p_backet);
	cJSON_Delete(pout_root);
	*/
	return g_outbuf;
}

const char* upgrade_res(const char* json) {
		cJSON *p_root = NULL;
		cJSON *p_para = NULL;	
		cJSON *p_tmp = NULL;
		eENC_ERROR code = BWENC_ERROR_UNKNOW;
	
		unsigned int update_op = 0;
	
		p_root = cJSON_Parse(json);
		if (p_root == NULL)
		{
			cgi_debug("parse root error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_para = cJSON_GetObjectItem(p_root, "param");
		if (p_para == NULL)
		{
			cgi_debug("parse para error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_tmp = cJSON_GetObjectItem(p_para, "type");
		if(NULL != p_tmp)
		{
			update_op = atoi(p_tmp->valuestring);
		}
		cJSON_Delete(p_root);
	
		if(1 == update_op)
		{
			//开始升级
		}
		else if(2 == update_op)
		{
			//查询
		}
	
		cJSON_Delete(p_root);
		return upgrade_status_response(update_op) ;
	
	error:
		cJSON_Delete(p_root);
		return bwenc_common_ack(code);; 
}

// TODO 系统设置-时间设置
int bw_comm_shell_exec(const char* cmdline, char* out, size_t out_len)
{
    FILE *pipe;
    char buf[1024] = {0};
    char result[SZ_64K];
    memset(result, 0, sizeof(result));
    char* p = result;
    if ( (pipe = popen(cmdline, "r")) != NULL )
    {
        while ( !feof(pipe) && !ferror(pipe) )
        {
            size_t n = fread(buf, 1, 1024, pipe);
            snprintf(p, sizeof(result)-strlen(result), "%s", buf);
            p += n;
        }
        pclose(pipe);
    }

    if (out) {
    	snprintf(out, out_len, "%s", result);
    }
	return 0;
}

int bw_comm_Set_NTPcfg(char *NTPserverIP)
{
	char val_str[256];
	char outbuf[256] = {0};
	
	if(NTPserverIP == NULL)
	{
		cgi_debug("NTP server ipaddr invalid");
	}

	memset(val_str,0,sizeof(val_str));
	sprintf(val_str, "./ntpdate %s &&hwclock -w & ",NTPserverIP);
	bw_comm_shell_exec(val_str, outbuf, sizeof(outbuf));

	cgi_debug("ntp out:%s", outbuf);
	std::string out_str = outbuf;
	size_t index1 = out_str.find("step time server");//adjust time server
	size_t index2 = out_str.find("adjust time server");//adjust time server
	if((index1 == std::string::npos) && (index2 == std::string::npos) )
	{
		return 1;
	}
	
	return 0;
}

eENC_ERROR setTime(NTP_INFO ntp_time)
{
	char cmd[SZ_1K] = {0};
	int ret = 0;

	if(ntp_time.type == 1)
	{
		memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),"hwclock --set --date	\'%s\' ",ntp_time.time);
		system(cmd);

        memset(cmd,0,sizeof(cmd));
		snprintf(cmd,sizeof(cmd),"hwclock --hctosys");
		system(cmd);
	}
	else if(ntp_time.type == 2)
	{
		ret = bw_comm_Set_NTPcfg( ntp_time.ntp);
	  	if(ret != 0 )
	  	{
	  		return BWENC_ERROR_UNKNOW;
	  	}
	}
	
	return BWENC_ERROR_NONE;
}

const char* time_set(const char* json) {
		cJSON *p_root = NULL;
		cJSON *p_para = NULL;	
		cJSON *p_tmp = NULL;
		eENC_ERROR code = BWENC_ERROR_UNKNOW;
		NTP_INFO ntp_time;
	
		//char time_buf[50] = {0};
		//char ntp_buf[50] = {0};
	
		//unsigned int time_op = 0;
	
		p_root = cJSON_Parse(json);
		if (p_root == NULL)
		{
			cgi_debug("parse root error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_para = cJSON_GetObjectItem(p_root, "param");
		if (p_para == NULL)
		{
			cgi_debug("parse para error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_tmp = cJSON_GetObjectItem(p_para, "type");
		if(NULL != p_tmp)
		{
			ntp_time.type = atoi(p_tmp->valuestring);
		}
	
		
		p_tmp = cJSON_GetObjectItem(p_para, "time");
		if(NULL != p_tmp)
		{
			snprintf(ntp_time.time,sizeof(ntp_time.time),"%s",p_tmp->valuestring);
		}
	
		p_tmp = cJSON_GetObjectItem(p_para, "ntp");
		if(NULL != p_tmp)
		{
			snprintf(ntp_time.ntp,sizeof(ntp_time.ntp),"%s",p_tmp->valuestring);
		}
	
		code = setTime(ntp_time);
	error:
		cJSON_Delete(p_root);
		return bwenc_common_ack(code);; 
}

// TODO 关机/重启
const char* shut_reboot(const char* json) {
		cJSON *p_root = NULL;
		cJSON *p_para = NULL;	
		cJSON *p_tmp = NULL;
		eENC_ERROR code = BWENC_ERROR_UNKNOW;
	
		unsigned int power_op = 0;
	
		p_root = cJSON_Parse(json);
		if (p_root == NULL)
		{
			cgi_debug("parse root error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_para = cJSON_GetObjectItem(p_root, "param");
		if (p_para == NULL)
		{
			cgi_debug("parse para error");
			code = BWENC_ERROR_INVALID_PARAM;
			goto error;
		}
	
		p_tmp = cJSON_GetObjectItem(p_para, "type");
		if(NULL != p_tmp)
		{
			power_op = atoi(p_tmp->valuestring);
		}
		cJSON_Delete(p_root);
	
		if(1 == power_op)
		{
			system("shutdown -h now");
		}
		else if(2 == power_op)
		{
			system("reboot");
		}
	
		cJSON_Delete(p_root);
		return NULL;
	
	error:
		cJSON_Delete(p_root);
		return bwenc_common_ack(code);; 
}

void log_write(int log_type, const char* detail) {
	char type_str[50] = { '\0' };

	switch (log_type) {
	case BWENC_LOG_DEVICE_ALARM:
		sprintf(type_str, "%s", "Alarm message");
		break;
	case BWENC_LOG_DEVICE_WORK:
		sprintf(type_str, "%s", "Work message");
		break;
	case BWENC_LOG_SYS_SET:
		sprintf(type_str, "%s", "Setting message");
		break;
	default:
		cgi_debug("log type error");
		return;
	}

	if (0 == strcmp(detail, "")) {
		cgi_debug("log detail empty:%s", detail);
		return;
	}

	BWSqlite db(BWENC_DATABASE);
	char sql[SZ_1K] = { '\0' };
	DateTime datetime;
	char timeStr[sizeof("yyyy-mm-dd hh:mm:ss")] = { '\0' };
	datetime.time2string(time(nullptr), timeStr);
	snprintf(sql, sizeof(sql),
			"INSERT INTO %s (%s,%s,%s) VALUES ('%s','%s','%s')",
			DBTBL_LOG, DBCOL_TYPE, DBCOL_DETAIL, DBCOL_TIME, type_str, detail,
			timeStr);

	if (SQLITE_OK != db.Exec(sql)) {
		cgi_debug("save log in db error");
	}
}
